package com.adminsystem.java.user.service.impl;

import com.adminsystem.java.common.PageResult;
import com.adminsystem.java.user.mapper.UserMapper;
import com.adminsystem.java.user.pojo.entity.User;
import com.adminsystem.java.user.pojo.param.*;
import com.adminsystem.java.common.Result;
import com.adminsystem.java.common.ResultCode;
import com.adminsystem.java.user.pojo.vo.LoginUserVO;
import com.adminsystem.java.user.pojo.vo.UserVO;
import com.adminsystem.java.user.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import com.adminsystem.java.utils.JwtUtil;

/**
 * @author wangpeiao
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;

    /**
     * 用户注册
     * @param param 注册参数
     * @return 注册结果
     */
    @Override
    public Result register(UserRegisterParam param) {
        log.info("用户注册请求参数: {}", param);

        // 检查用户名是否已存在
        User userByUsername = userMapper.findByUsername(param.getUsername());
        if (userByUsername != null) {
            return Result.fail(ResultCode.USERNAME_EXIST);
        }

        // 检查邮箱是否已存在
        User userByEmail = userMapper.findByEmail(param.getEmail());
        if (userByEmail != null) {
            return Result.fail(ResultCode.EMAIL_EXIST);
        }

        User user = new User();
        user.setUsername(param.getUsername());
        user.setEmail(param.getEmail());
        // 使用 BCrypt 加密密码
        user.setPassword(passwordEncoder.encode(param.getPassword()));
        user.setStatus(1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String now = LocalDateTime.now().format(formatter);
        user.setCreateTime(now);
        user.setUpdateTime(now);

        int insertResult = userMapper.insertUser(user);
        if (insertResult > 0) {
            log.info("用户注册成功，用户名: {}", param.getUsername());
            return Result.success(null);
        } else {
            log.error("用户注册失败，用户名: {}", param.getUsername());
            return Result.fail(ResultCode.FAILED);
        }
    }

    /**
     * 用户登录
     * @param param 登录参数
     * @return 登录结果
     */
    @Override
    public Result<LoginUserVO> login(UserLoginParam param) {
        log.info("用户登录请求参数: {}", param);
        User user = userMapper.findByUsername(param.getUsername());
        if (user == null) {
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }
        if (!passwordEncoder.matches(param.getPassword(), user.getPassword())) {
            return Result.fail(ResultCode.PASSWORD_ERROR);
        }
        if (user.getStatus() != null && user.getStatus() == 0) {
            return Result.fail(ResultCode.USER_DISABLED);
        }

        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtils.copyProperties(user, loginUserVO);
        String token = jwtUtil.generateToken(user.getUsername());
        loginUserVO.setToken(token);

        log.info("用户登录成功，用户信息：{}", loginUserVO);
        return Result.success(loginUserVO);
    }

    /**
     * 忘记密码
     * @param param 忘记密码参数
     * @return 忘记密码结果
     */
    @Override
    public Result forgotPassword(ForgotPasswordParam param) {
        log.info("用户忘记密码请求参数: {}", param);
        String input = param.getUsernameOrEmail();
        User user = null;

        // 判断是邮箱还是用户名
        if (input.contains("@")) {
            user = userMapper.findByEmail(input);
        } else {
            user = userMapper.findByUsername(input);
        }

        if (user == null) {
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }

        // 生成验证码（6位）
        String code = String.format("%06d", new Random().nextInt(999999));

        // 存储验证码和过期时间（比如 5 分钟）
        user.setResetCode(code);
        user.setResetCodeExpiry(LocalDateTime.now().plusMinutes(5));
        userMapper.updateUser(user);
        log.info("用户忘记密码，用户名: {}，验证码: {}", user.getUsername(), code);

        // 直接返回验证码给前端
        return Result.success(null, "验证码: " + code);
    }

    /**
     * 重置密码
     * @param param 重置密码参数
     * @return 重置密码结果
     */
    @Override
    public Result resetPassword(ResetPasswordParam param) {
        log.info("用户重置密码请求参数: {}", param);
        String input = param.getUsernameOrEmail();

        // 查询用户
        User user = null;
        if (input.contains("@")) {
            user = userMapper.findByEmail(input);
        } else {
            user = userMapper.findByUsername(input);
        }

        if (user == null) {
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }

        // 检查验证码是否匹配 & 是否过期
        if (user.getResetCode() == null || !user.getResetCode().equals(param.getCode())) {
            log.info("用户重置密码验证码错误，用户名: {}", input);
            return Result.fail(ResultCode.FAILED, "验证码错误");
        }

        if (LocalDateTime.now().isAfter(user.getResetCodeExpiry())) {
            log.info("用户重置密码验证码已过期，用户名: {}", input);
            return Result.fail(ResultCode.FAILED, "验证码已过期");
        }

        // 校验两次密码是否一致
        if (!param.getNewPassword().equals(param.getConfirmPassword())) {
            log.info("用户重置密码两次输入密码不一致，用户名: {}", input);
            return Result.fail(ResultCode.VALIDATE_FAILED, "两次输入密码不一致");
        }

        // 更新密码 + 清除验证码
        user.setPassword(passwordEncoder.encode(param.getNewPassword()));
        user.setResetCode(null);
        user.setResetCodeExpiry(null);
        userMapper.updateUser(user);
        log.info("用户重置密码成功，用户名: {}", input);

        return Result.success(null);
    }

    /**
     * 获取用户列表
     * @param param 分页参数
     * @return 用户列表
     */
    @Override
    public PageResult<UserVO> getUserListByPage(UserPageParam param) {
        int pageNum = param.getPageNum();
        int pageSize = param.getPageSize();

        // 使用 PageHelper 开始分页
        PageHelper.startPage(pageNum, pageSize);

        // 查询数据
        List<User> users = userMapper.findUsersByCondition(
                param.getUsername(),
                param.getPhone(),
                param.getGender(),
                param.getStatus()
        );
        // 获取分页信息
        PageInfo<User> pageInfo = new PageInfo<>(users);

        // 转换 VO
        List<UserVO> userVOs = users.stream()
                .map(user -> {
                    UserVO vo = new UserVO();
                    BeanUtils.copyProperties(user, vo);
                    return vo;
                })
                .collect(Collectors.toList());

        // 返回 PageResult
        PageResult<UserVO> result = new PageResult<>();
        result.setList(userVOs);
        result.setTotal(pageInfo.getTotal());
        result.setPageNum(pageNum);
        result.setPageSize(pageSize);
        result.setTotalPages(pageInfo.getPages());
        log.info("用户列表查询结果result: {}", result);
        return result;
    }

    /**
     * 获取用户详情
     * @param username 用户名
     * @return 用户详情
     */
    @Override
    public Result<UserVO> getUserDetail(String username) {
        log.info("用户详情查询请求参数: {}", username);
        User user = userMapper.findByUsername(username);
        if (user == null) {
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }
        UserVO vo = new UserVO();
        BeanUtils.copyProperties(user, vo);
        return Result.success(vo);
    }

    /**
     * 编辑用户信息
     * @param param 编辑用户信息参数
     * @return 编辑结果
     */
    @Override
    public Result<Void> editUser(UserEditParam param) {
        log.info("开始编辑用户信息，参数: {}", param);

        // 查询用户是否存在
        User user = userMapper.findByUsername(param.getUsername());
        if (user == null) {
            log.warn("尝试编辑不存在的用户，用户名: {}", param.getUsername());
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }

        // 更新字段
        user.setRealName(param.getRealName());
        user.setEmail(param.getEmail());
        user.setPhone(param.getPhone());
        user.setGender(param.getGender());
        user.setStatus(param.getStatus());

        int rows = userMapper.updateUserInfo(user);
        if (rows > 0) {
            log.info("用户信息更新成功，用户名: {}", param.getUsername());
            return Result.success(null);
        } else {
            log.error("用户信息更新失败，用户名: {}", param.getUsername());
            return Result.fail(ResultCode.FAILED);
        }
    }

    /**
     * 删除用户
     * @param username 用户名
     * @return 删除结果
     */
    @Override
    public Result<Void> deleteUser(String username) {
        log.info("开始删除用户，用户名: {}", username);

        User user = userMapper.findByUsername(username);
        if (user == null) {
            log.warn("尝试删除不存在的用户，用户名: {}", username);
            return Result.fail(ResultCode.USERNAME_NOT_EXIST);
        }

        int rows = userMapper.deleteUser(username);
        if (rows > 0) {
            log.info("用户删除成功，用户名: {}", username);
            return Result.success(null);
        } else {
            log.error("用户删除失败，用户名: {}", username);
            return Result.fail(ResultCode.FAILED);
        }
    }

    /**
     * 新增用户
     * @param param 新增用户参数
     * @return 新增结果
     */
    @Override
    public Result<Void> addUser(UserAddParam param) {
        log.info("开始新增用户，参数: {}", param);

        // 检查用户名是否已存在
        User userByUsername = userMapper.findByUsername(param.getUsername());
        if (userByUsername != null) {
            log.warn("用户名已存在：{}", param.getUsername());
            return Result.fail(ResultCode.USERNAME_EXIST);
        }

        // 检查邮箱是否已存在
        User userByEmail = userMapper.findByEmail(param.getEmail());
        if (userByEmail != null) {
            log.warn("邮箱已存在：{}", param.getEmail());
            return Result.fail(ResultCode.EMAIL_EXIST);
        }

        // 构建用户实体
        User user = new User();
        user.setUsername(param.getUsername());
        user.setEmail(param.getEmail());
        user.setRealName(param.getRealName());
        user.setPassword(passwordEncoder.encode(param.getPassword()));
        user.setPhone(param.getPhone());
        user.setGender(param.getGender());
        user.setStatus(param.getStatus());

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String now = LocalDateTime.now().format(formatter);
        user.setCreateTime(now);
        user.setUpdateTime(now);

        int insertResult = userMapper.insertUser(user);
        if (insertResult > 0) {
            return Result.success(null);
        } else {
            return Result.fail(ResultCode.FAILED);
        }
    }

    @Override
    public Result<Void> changeUserStatus(String username, Integer status) {
        log.info("开始修改用户状态，用户名: {}，状态: {}", username, status);
        if (username == null || username.trim().isEmpty()) {
            return Result.fail(ResultCode.VALIDATE_FAILED, "用户名不能为空");
        }
        if (status == null || (status != 0 && status != 1)) {
            return Result.fail(ResultCode.VALIDATE_FAILED, "状态值非法");
        }
        try {
            int count = userMapper.updateUserStatus(username, status);
            if (count > 0) {
                log.info("用户状态修改成功，用户名: {}，状态: {}", username, status);
                return Result.success(null);
            } else {
                log.warn("用户状态修改失败，用户名: {}，状态: {}", username, status);
                return Result.fail(ResultCode.USERNAME_NOT_EXIST, "用户不存在");
            }
        } catch (Exception e) {
            log.error("修改用户状态异常，用户名: {}，状态: {}，异常: {}", username, status, e.getMessage(), e);
            return Result.fail(ResultCode.FAILED, "服务器异常");
        }
    }

    @Override
    public Result<Void> deleteUsersByIds(UserDeleteByIdsParam param) {
        List<Long> ids = param.getIds();
        if (ids.isEmpty()) {
            return Result.fail(ResultCode.VALIDATE_FAILED, "用户ID列表为空");
        }

        int rows = userMapper.deleteUsersByIds(ids);
        if (rows > 0) {
            log.info("成功批量删除 {} 个用户", rows);
            return Result.success(null);
        } else {
            log.warn("未找到要删除的用户，可能ID不存在");
            return Result.fail(ResultCode.FAILED, "删除失败，请检查用户是否存在");
        }
    }

}